package com.wfh.picture.service.impl;

import cn.hutool.core.util.ObjUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.wfh.picture.exception.BusinessException;
import com.wfh.picture.exception.ErrorCode;
import com.wfh.picture.exception.ThrowUtils;
import com.wfh.picture.model.dto.space.analyze.*;
import com.wfh.picture.model.entity.Picture;
import com.wfh.picture.model.entity.Space;
import com.wfh.picture.model.entity.User;
import com.wfh.picture.model.vo.space.analyze.*;
import com.wfh.picture.service.PictureService;
import com.wfh.picture.service.SpaceAnalyzeService;
import com.wfh.picture.service.SpaceService;
import com.wfh.picture.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;

/**
 * @Author FengHuan Wang
 * @Date 2025/5/16 16:00
 * @Version 1.0
 */
@Service
@Slf4j
public class SpaceAnalyzeServiceImpl implements SpaceAnalyzeService {


    @Resource
    private UserService userService;


    @Resource
    private SpaceService spaceService;


    @Resource
    private PictureService pictureService;

    /**
     * 校验空间分析权限
     *
     * @param spaceAnalyzeRequest
     * @param loginUser
     */
    private void checkSpaceAnalyzeAuth(SpaceAnalyzeRequest spaceAnalyzeRequest, User loginUser) {
        Long spaceId = spaceAnalyzeRequest.getSpaceId();
        boolean queryPublic = spaceAnalyzeRequest.isQueryPublic();
        boolean queryAll = spaceAnalyzeRequest.isQueryAll();
        Space space = spaceService.getById(spaceId);
        if (queryPublic || queryAll) {
            ThrowUtils.throwIf(!userService.isAdmin(loginUser), ErrorCode.NO_AUTH_ERROR);
        } else {
            // 分析特定空间，仅仅本人和管理员可以访问
            checkSpaceAuth(loginUser, space);
            ThrowUtils.throwIf(space == null, ErrorCode.NOT_FOUND_ERROR);

        }

    }

    /**
     * 检查空间权限
     *
     * @param loginUser
     * @param space
     */
    @Override
    public void checkSpaceAuth(User loginUser, Space space) {
        // 仅仅本人和管理员课编辑
        ThrowUtils.throwIf(!space.getUserId().equals(loginUser.getId()) && !userService.isAdmin(loginUser), ErrorCode.NO_AUTH_ERROR);
    }

    /**
     * 获取空间使用情况分析
     *
     * @param spaceUsageAnalyzeRequest
     * @param loginUser
     * @return
     */
    @Override
    public SpaceUsageAnalyzeResponse getSpaceUsageAnalyze(SpaceUsageAnalyzeRequest spaceUsageAnalyzeRequest, User loginUser) {
        // 校验参数
        // 全空间或公共图库需要从Picture表中查询
        if (spaceUsageAnalyzeRequest.isQueryAll() || spaceUsageAnalyzeRequest.isQueryPublic()) {
            // 校验权限
            checkSpaceAnalyzeAuth(spaceUsageAnalyzeRequest, loginUser);
            // 统计公共图库的使用
            LambdaQueryWrapper<Picture> lambdaQueryWrapper = new LambdaQueryWrapper<Picture>()
                    .select(Picture::getPicSize);
            // 补充查询范围
            fillAnalyzeLambdaQueryWrapper(spaceUsageAnalyzeRequest, lambdaQueryWrapper);
            // 查询
            List<Object> pictureList = pictureService.getBaseMapper().selectObjs(lambdaQueryWrapper);
            long usedSize = pictureList.stream().mapToLong(obj -> (Long) obj).sum();
            int usedCount = pictureList.size();
            // 封装返回结果
            SpaceUsageAnalyzeResponse usageAnalyzeResponse = SpaceUsageAnalyzeResponse.builder()
                    .usedSize(usedSize)
                    .usedCount(Long.valueOf(usedCount))
                    .build();
            return usageAnalyzeResponse;
        } else {
            // 特定空间中查询
            Long spaceId = spaceUsageAnalyzeRequest.getSpaceId();
            // 判断spaceId是否为空
            if (spaceId == null) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "空间不存在");
            }
            Space space = spaceService.getById(spaceId);
            ThrowUtils.throwIf(space == null, ErrorCode.NOT_FOUND_ERROR);
            // 校验权限
            checkSpaceAuth(loginUser, space);
            // 构建返回结果
            SpaceUsageAnalyzeResponse usageAnalyzeResponse = SpaceUsageAnalyzeResponse.builder()
                    .usedSize(space.getTotalSize())
                    .usedCount(space.getTotalCount())
                    .maxCount(space.getMaxCount())
                    .maxSize(space.getMaxSize())
                    // 设置百分比
                    .sizeUsageRatio(space.getTotalSize().doubleValue() / space.getMaxSize().doubleValue())
                    // 设置百分比
                    .countUsageRatio(space.getTotalCount().doubleValue() / space.getMaxCount().doubleValue())
                    .build();
            return usageAnalyzeResponse;
        }
    }

    /**
     * 获取空间分类分析
     *
     * @param spaceCategoryAnalyzeRequest
     * @param loginUser
     * @return
     * todo bug待修复
     * java.lang.NullPointerException: Cannot invoke "Object.toString()" because the return value of "java.util.Map.get(Object)" is null
     */
    @Override
    public List<SpaceCategoryAnalyzeResponse> getSpaceCategoryAnalyze(SpaceCategoryAnalyzeRequest spaceCategoryAnalyzeRequest, User loginUser) {
        ThrowUtils.throwIf(spaceCategoryAnalyzeRequest == null, ErrorCode.PARAMS_ERROR);
        // 检查权限
        checkSpaceAnalyzeAuth(spaceCategoryAnalyzeRequest, loginUser);
        // 查询
        QueryWrapper<Picture> lambdaQueryWrapper = new QueryWrapper<>();
        // 填充查询参数
        fillAnalyzeQueryWrapper(spaceCategoryAnalyzeRequest, lambdaQueryWrapper);
        // 查询
        lambdaQueryWrapper
                .select("category", "COUNT(*) AS count", "SUM(picSize) AS totalSize")
                .groupBy("category");
        // 查询
        List<SpaceCategoryAnalyzeResponse> analyzeResponseList = pictureService.getBaseMapper().selectMaps(lambdaQueryWrapper)
                .stream().map(map -> {
                    String category = map.get("category").toString();
                    Long count = (Long) map.get("count");
                    Long totalSize = (Long) map.get("totalSize");
                    return new SpaceCategoryAnalyzeResponse(category, count, totalSize);
                }).collect(Collectors.toList());
        return analyzeResponseList;
    }

    /**
     * 获取空间图片表情按分析
     *
     * @param spaceTagAnalyzeRequest
     * @param loginUser
     * @return
     */
    @Override
    public List<SpaceTagAnalyzeResponse> getSpaceTagAnalyze(SpaceTagAnalyzeRequest spaceTagAnalyzeRequest, User loginUser) {
        // 校验参数
        ThrowUtils.throwIf(spaceTagAnalyzeRequest == null, ErrorCode.PARAMS_ERROR);

        // 构造查询条件
        QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
        // 填充查询参数
        fillAnalyzeQueryWrapper(spaceTagAnalyzeRequest, queryWrapper);
        // 查询所有符合条件的标签
        queryWrapper.select("tags");
        List<Object> objectList = pictureService.getBaseMapper().selectObjs(queryWrapper);
        List<String> tagsStrList = objectList.stream().filter(ObjUtil::isNotNull)
                .map(Object::toString)
                .collect(Collectors.toList());
        Map<String, Long> tagsCountMap = tagsStrList.stream()
                .flatMap(tagsStr -> JSONUtil.toList(tagsStr, String.class).stream())
                .collect(Collectors.groupingBy(tags -> tags, Collectors.counting()));
        // 转化为响应对象并排序
        List<SpaceTagAnalyzeResponse> resultList = tagsCountMap.entrySet().stream()
                .sorted((e1, e2) -> e2.getValue().compareTo(e1.getValue()))
                .map(entry -> new SpaceTagAnalyzeResponse(entry.getKey(), entry.getValue()))
                .collect(Collectors.toList());

        return resultList;
    }

    /**
     * 获取空间大小分析
     *
     * @param spaceSizeAnalyzeRequest
     * @param loginUser
     * @return
     */
    @Override
    public List<SpaceSizeAnalyzeResponse> getSpaceSizeAnalyzeRequestList(SpaceSizeAnalyzeRequest spaceSizeAnalyzeRequest, User loginUser) {
        // 校验参数
        ThrowUtils.throwIf(spaceSizeAnalyzeRequest == null, ErrorCode.PARAMS_ERROR);
        // 检查权限
        checkSpaceAnalyzeAuth(spaceSizeAnalyzeRequest, loginUser);
        // 构造查询条件
        QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
        // 填充查询参数
        fillAnalyzeQueryWrapper(spaceSizeAnalyzeRequest, queryWrapper);
        // 查询
        queryWrapper.select("picSize");
        List<Long> pictureSizeList = pictureService.getBaseMapper().selectObjs(queryWrapper)
                .stream().filter(ObjUtil::isNotNull)
                .map(size -> Long.parseLong(size.toString()))
                .collect(Collectors.toList());
        // 定义分段范围，注意使用有序的Map
        Map<String, Long> sizeCountMap = new LinkedHashMap<>();
        sizeCountMap.put("<100KB", pictureSizeList.stream().filter(size -> size < 100 * 1024).count());
        sizeCountMap.put("100KB-1MB", pictureSizeList.stream().filter(size -> size >= 100 * 1024 && size < 1024 * 1024).count());
        sizeCountMap.put("1MB-10MB", pictureSizeList.stream().filter(size -> size >= 1024 * 1024 && size < 10 * 1024 * 1024).count());
        sizeCountMap.put("10MB-100MB", pictureSizeList.stream().filter(size -> size >= 10 * 1024 * 1024 && size < 100 * 1024 * 1024).count());
        sizeCountMap.put("100MB-1GB", pictureSizeList.stream().filter(size -> size >= 100 * 1024 * 1024 && size < 1024 * 1024 * 1024).count());
        // 转化为响应对象
        List<SpaceSizeAnalyzeResponse> resultList = sizeCountMap.entrySet().stream()
                .map(entry -> new SpaceSizeAnalyzeResponse(entry.getKey(), entry.getValue()))
                .collect(Collectors.toList());
        return resultList;
    }

    /**
     * 获取用剑用户行为分析
     *
     * @param spaceUserAnalyzeRequest
     * @param loginUser
     * @return
     */
    @Override
    public List<SpaceUserAnalyzeResponse> getSpaceUserAnalyze(SpaceUserAnalyzeRequest spaceUserAnalyzeRequest, User loginUser) {
        // 校验参数
        ThrowUtils.throwIf(spaceUserAnalyzeRequest == null, ErrorCode.PARAMS_ERROR);
        // 检查权限
        checkSpaceAnalyzeAuth(spaceUserAnalyzeRequest, loginUser);
        // 构造查询条件
        QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
        // 填充查询参数
        fillAnalyzeQueryWrapper(spaceUserAnalyzeRequest, queryWrapper);
        // 查询
        queryWrapper.select("userId");
        // 补充分析维度
        String timeDimension = spaceUserAnalyzeRequest.getTimeDimension();
        switch (timeDimension) {
            case "day":
                queryWrapper.select("DATE_FORMAT(createTime, '%Y-%m-%d') as period", "count(*) as count");
                break;
            case "week":
                queryWrapper.select("YEARWEEK(createTime) as period", "count(*) as count");
                break;
            case "month":
                queryWrapper.select("DATE_FORMAT(createTime, '%Y-%m') as period", "count(*) as count");
                break;
            default:
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "无效的时间维度");
        }
        // 分组排序
        queryWrapper.groupBy("period").orderByAsc("period");
        // 查询并封装返回结果
        List<SpaceUserAnalyzeResponse> resultList = pictureService.getBaseMapper().selectMaps(queryWrapper)
                .stream().map(map -> {
                    SpaceUserAnalyzeResponse response = new SpaceUserAnalyzeResponse();
                    response.setPeriod(map.get("period").toString());
                    response.setCount(Long.parseLong(map.get("count").toString()));
                    return response;
                }).collect(Collectors.toList());
        return resultList;
    }


    /**
     * 获取空间排行分析
     * @param spaceRankAnalyzeRequest
     * @param loginUser
     * @return
     */
    @Override
    public List<Space> getSpaceRankAnalyze(SpaceRankAnalyzeRequest spaceRankAnalyzeRequest, User loginUser) {
        // 校验参数
        ThrowUtils.throwIf(spaceRankAnalyzeRequest == null, ErrorCode.PARAMS_ERROR);
        // 检查权限
        ThrowUtils.throwIf(!userService.isAdmin(loginUser), ErrorCode.NO_AUTH_ERROR);

        // 构造查询条件
        LambdaQueryWrapper<Space> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        // 填充查询参数
        lambdaQueryWrapper.select(Space::getId, Space::getSpaceName, Space::getUserId, Space::getTotalSize)
                .orderByDesc(Space::getTotalSize)
                .last("limit " + spaceRankAnalyzeRequest.getTopN());
        // 查询并封装返回结果
        return spaceService.list(lambdaQueryWrapper);
    }


    /**
     * 填充查询参数
     *
     * @param spaceAnalyzeRequest
     * @param lambdaQueryWrapper
     */
    private void fillAnalyzeLambdaQueryWrapper(SpaceAnalyzeRequest spaceAnalyzeRequest, LambdaQueryWrapper<Picture> lambdaQueryWrapper) {
        // 根据请求参数封装查询条件
        Long spaceId = spaceAnalyzeRequest.getSpaceId();
        boolean queryPublic = spaceAnalyzeRequest.isQueryPublic();
        boolean queryAll = spaceAnalyzeRequest.isQueryAll();
        if (queryAll) {
            return;
        }
        // 公共图库
        if (queryPublic) {
            lambdaQueryWrapper.isNull(Picture::getSpaceId);
            return;
        }
        // 特定空间
        if (spaceId != null) {
            lambdaQueryWrapper.eq(Picture::getSpaceId, spaceId);
            return;
        }
        throw new BusinessException(ErrorCode.PARAMS_ERROR, "未指定查询条件");
    }


    private void fillAnalyzeQueryWrapper(SpaceAnalyzeRequest spaceAnalyzeRequest, QueryWrapper<Picture> queryWrapper) {
        // 根据请求参数封装查询条件
        Long spaceId = spaceAnalyzeRequest.getSpaceId();
        boolean queryPublic = spaceAnalyzeRequest.isQueryPublic();
        boolean queryAll = spaceAnalyzeRequest.isQueryAll();
        if (queryAll) {
            return;
        }
        // 公共图库
        if (queryPublic) {
            queryWrapper.isNull("spaceId");
            return;
        }
        // 特定空间
        if (spaceId != null) {
            queryWrapper.eq("spaceId", spaceId);
            return;
        }
        throw new BusinessException(ErrorCode.PARAMS_ERROR, "未指定查询条件");
    }
}
